package middleware

import (
	"reflect"

	"code.cloudfoundry.org/bytefmt"
	"github.com/flosch/pongo2"
)

func filterKey(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
	if in.IsNil() || param.IsNil() {
		return pongo2.AsValue(nil), nil
	}
	key := reflect.Indirect(reflect.ValueOf(param.Interface()))
	val := reflect.Indirect(reflect.ValueOf(in.Interface()))
	if val.Kind() == reflect.Struct {
		ret := val.FieldByName(param.String())
		if !ret.IsValid() {
			return pongo2.AsValue(nil), nil
		}
		return pongo2.AsValue(ret.Interface()), nil
	}
	ret := val.MapIndex(key)
	if !ret.IsValid() {
		return pongo2.AsValue(nil), nil
	}
	return pongo2.AsValue(ret.Interface()), nil
}

func filterExists(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
	if !isEmpty(in) {
		return in, nil
	}
	return pongo2.AsValue(param), nil
}

func isEmpty(in *pongo2.Value) bool {
	if in.IsNil() {
		return true
	}
	if in.IsString() && in.String() == "" {
		return true
	}
	if in.IsInteger() && in.Integer() == 0 {
		return true
	}
	if in.IsBool() && !in.Bool() {
		return true
	}
	if in.IsFloat() && in.Float() == 0 {
		return true
	}
	if in.CanSlice() && in.Len() == 0 {
		return true
	}
	return false
}

func filterJsonEncode(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
	body, err := json.Marshal(in.Interface())
	if err != nil {
		return nil, &pongo2.Error{
			Sender:    "filter:jsonencode",
			OrigError: err,
		}
	}
	return pongo2.AsValue(string(body)), nil
}

func filterIBytes(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
	var multiple float64 = 1
	if param.IsFloat() {
		multiple = param.Float()
	}
	if param.IsInteger() {
		multiple = float64(param.Integer())
	}
	if in.IsFloat() {
		val := in.Float() * multiple
		return pongo2.AsValue(bytefmt.ByteSize(uint64(val))), nil
	}
	if in.IsInteger() {
		val := float64(in.Integer()) * multiple
		return pongo2.AsValue(bytefmt.ByteSize(uint64(val))), nil
	}
	return pongo2.AsValue(nil), nil
}

func init() {
	pongo2.RegisterFilter("key", filterKey)
	pongo2.RegisterFilter("exists", filterExists)
	pongo2.RegisterFilter("jsonencode", filterJsonEncode)
	pongo2.RegisterFilter("ibytes", filterIBytes)
}
